home *** CD-ROM | disk | FTP | other *** search
- Subject: v08i011: A Micro-Emacs variant that resembles GNU Emacs
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: Bob Larson <seismo!usc-oberon!blarson>
- Mod.sources: Volume 8, Issue 11
- Archive-name: micrognu/Part04
-
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # search.c
- # symbol.c
- # window.c
- # tty/termcap/tty.c
- # tty/termcap/readme
- # tty/termcap/ttydef.h
- # This archive created: Sat Nov 15 15:06:50 1986
- export PATH; PATH=/bin:$PATH
- if test ! -d sys
- then
- mkdir sys
- fi
- if test ! -d tty
- then
- mkdir tty
- fi
- if test ! -d tty/termcap
- then
- mkdir tty/termcap
- fi
- if test -f 'search.c'
- then
- echo shar: will not over-write existing file "'search.c'"
- else
- cat << \SHAR_EOF > 'search.c'
- /*
- * Search commands.
- * The functions in this file implement the
- * search commands (both plain and incremental searches
- * are supported) and the query-replace command.
- *
- * The plain old search code is part of the original
- * MicroEMACS "distribution". The incremental search code,
- * and the query-replace code, is by Rich Ellison.
- */
- #include "def.h"
-
- #define SRCH_BEGIN (0) /* Search sub-codes. */
- #define SRCH_FORW (-1)
- #define SRCH_BACK (-2)
- #define SRCH_NOPR (-3)
- #define SRCH_ACCM (-4)
- #define SRCH_MARK (-5)
-
- typedef struct {
- int s_code;
- LINE *s_dotp;
- int s_doto;
- } SRCHCOM;
-
- static SRCHCOM cmds[NSRCH];
- static int cip;
-
- int srch_lastdir = SRCH_NOPR; /* Last search flags. */
-
- /*
- * Search forward.
- * Get a search string from the user, and search for it,
- * starting at ".". If found, "." gets moved to just after the
- * matched characters, and display does all the hard stuff.
- * If not found, it just prints a message.
- */
- /*ARGSUSED*/
- forwsearch(f, n, k) {
- register int s;
-
- if ((s=readpattern("Search")) != TRUE)
- return (s);
- if (forwsrch() == FALSE) {
- ewprintf("Search failed: \"%s\"", pat);
- return (FALSE);
- }
- srch_lastdir = SRCH_FORW;
- return (TRUE);
- }
-
- /*
- * Reverse search.
- * Get a search string from the user, and search, starting at "."
- * and proceeding toward the front of the buffer. If found "." is left
- * pointing at the first character of the pattern [the last character that
- * was matched].
- */
- /*ARGSUSED*/
- backsearch(f, n, k) {
- register int s;
-
- if ((s=readpattern("Search backward")) != TRUE)
- return (s);
- if (backsrch() == FALSE) {
- ewprintf("Search failed: \"%s\"", pat);
- return (FALSE);
- }
- srch_lastdir = SRCH_BACK;
- return (TRUE);
- }
-
- /*
- * Search again, using the same search string
- * and direction as the last search command. The direction
- * has been saved in "srch_lastdir", so you know which way
- * to go.
- */
- /*ARGSUSED*/
- searchagain(f, n, k) {
- if (srch_lastdir == SRCH_FORW) {
- if (forwsrch() == FALSE) {
- ewprintf("Search failed: \"%s\"", pat);
- return (FALSE);
- }
- return (TRUE);
- }
- if (srch_lastdir == SRCH_BACK) {
- if (backsrch() == FALSE) {
- ewprintf("Search failed: \"%s\"", pat);
- return (FALSE);
- }
- return (TRUE);
- }
- ewprintf("No last search");
- return (FALSE);
- }
-
- /*
- * Use incremental searching, initially in the forward direction.
- * isearch ignores any explicit arguments.
- */
- /*ARGSUSED*/
- forwisearch(f, n, k) {
- return (isearch(SRCH_FORW));
- }
-
- /*
- * Use incremental searching, initially in the reverse direction.
- * isearch ignores any explicit arguments.
- */
- /*ARGSUSED*/
- backisearch(f, n, k) {
- return (isearch(SRCH_BACK));
- }
-
- /*
- * Incremental Search.
- * dir is used as the initial direction to search.
- * ^S switch direction to forward
- * ^R switch direction to reverse
- * ^Q quote next character (allows searching for ^N etc.)
- * <ESC> exit from Isearch
- * <DEL> undoes last character typed. (tricky job to do this correctly).
- * other ^ exit search, don't set mark
- * else accumulate into search string
- */
- isearch(dir) {
- register int c;
- register LINE *clp;
- register int cbo;
- register int success;
- int pptr;
- char opat[NPAT];
-
- for (cip=0; cip<NSRCH; cip++)
- cmds[cip].s_code = SRCH_NOPR;
- (VOID) strcpy(opat, pat);
- cip = 0;
- pptr = -1;
- clp = curwp->w_dotp;
- cbo = curwp->w_doto;
- is_lpush();
- is_cpush(SRCH_BEGIN);
- success = TRUE;
- is_prompt(dir, TRUE, success);
- for (;;) {
- update();
- switch (c = (char) getkey(KQUOTE)) {
- case METACH:
- srch_lastdir = dir;
- curwp->w_markp = clp;
- curwp->w_marko = cbo;
- if (kbdmop == NULL) ewprintf("Mark set");
- return (TRUE);
-
- case CCHR('G'):
- if (success != TRUE) {
- while (is_peek() == SRCH_ACCM)
- if (is_undo(&pptr, &dir) == FALSE)
- break;
- success = TRUE;
- is_prompt(dir, pptr < 0, success);
- break;
- }
- curwp->w_dotp = clp;
- curwp->w_doto = cbo;
- curwp->w_flag |= WFMOVE;
- srch_lastdir = dir;
- (VOID) ctrlg(FALSE, 0, KRANDOM);
- (VOID) strcpy(pat, opat);
- return ABORT;
-
- case CCHR('S'):
- if (dir == SRCH_BACK) {
- dir = SRCH_FORW;
- is_lpush();
- is_cpush(SRCH_FORW);
- success = TRUE;
- }
- if (success==FALSE && dir==SRCH_FORW)
- break;
- is_lpush();
- pptr = strlen(pat);
- (VOID) forwchar(FALSE, 1, KRANDOM);
- if (is_find(SRCH_FORW) != FALSE) is_cpush(SRCH_MARK);
- else {
- (VOID) backchar(FALSE, 1, KRANDOM);
- ttbeep();
- success = FALSE;
- }
- is_prompt(dir, pptr < 0, success);
- break;
-
- case CCHR('R'):
- if (dir == SRCH_FORW) {
- dir = SRCH_BACK;
- is_lpush();
- is_cpush(SRCH_BACK);
- success = TRUE;
- }
- if (success==FALSE && dir==SRCH_BACK)
- break;
- is_lpush();
- pptr = strlen(pat);
- (VOID) backchar(FALSE, 1, KRANDOM);
- if (is_find(SRCH_BACK) != FALSE) is_cpush(SRCH_MARK);
- else {
- (VOID) forwchar(FALSE, 1, KRANDOM);
- ttbeep();
- success = FALSE;
- }
- is_prompt(dir, pptr < 0, success);
- break;
-
- case 0x7F:
- if (is_undo(&pptr, &dir) != TRUE) return FALSE;
- if (is_peek() != SRCH_ACCM) success = TRUE;
- is_prompt(dir, pptr < 0, success);
- break;
-
- case CCHR('Q'):
- c = (char) getkey(KQUOTE);
- goto addchar;
- case CCHR('M'):
- c = CCHR('J');
- case CCHR('J'):
- goto addchar;
-
- default:
- if (ISCTRL(c) != FALSE) {
- c += '@';
- c |= KCTRL;
- success = execute((KEY) c, FALSE, 1);
- curwp->w_markp = clp;
- curwp->w_marko = cbo;
- if (kbdmop == NULL) ewprintf("Mark set");
- curwp->w_flag |= WFMOVE;
- return (success);
- }
- addchar:
- if (pptr == -1)
- pptr = 0;
- if (pptr == 0)
- success = TRUE;
- pat[pptr++] = c;
- if (pptr == NPAT) {
- ewprintf("Pattern too long");
- return FALSE;
- }
- pat[pptr] = '\0';
- is_lpush();
- if (success != FALSE) {
- if (is_find(dir) != FALSE)
- is_cpush(c);
- else {
- success = FALSE;
- ttbeep();
- is_cpush(SRCH_ACCM);
- }
- } else
- is_cpush(SRCH_ACCM);
- is_prompt(dir, FALSE, success);
- }
- }
- }
-
- is_cpush(cmd) register int cmd; {
- if (++cip >= NSRCH)
- cip = 0;
- cmds[cip].s_code = cmd;
- }
-
- is_lpush() {
- register int ctp;
-
- ctp = cip+1;
- if (ctp >= NSRCH)
- ctp = 0;
- cmds[ctp].s_code = SRCH_NOPR;
- cmds[ctp].s_doto = curwp->w_doto;
- cmds[ctp].s_dotp = curwp->w_dotp;
- }
-
- is_pop() {
- if (cmds[cip].s_code != SRCH_NOPR) {
- curwp->w_doto = cmds[cip].s_doto;
- curwp->w_dotp = cmds[cip].s_dotp;
- curwp->w_flag |= WFMOVE;
- cmds[cip].s_code = SRCH_NOPR;
- }
- if (--cip <= 0)
- cip = NSRCH-1;
- }
-
- is_peek() {
- return cmds[cip].s_code;
- }
-
- is_undo(pptr, dir) register int *pptr; register int *dir; {
- register int redo = FALSE ;
- switch (cmds[cip].s_code) {
- case SRCH_BEGIN:
- case SRCH_NOPR:
- *pptr = -1;
- case SRCH_MARK:
- break;
-
- case SRCH_FORW:
- *dir = SRCH_BACK;
- redo = TRUE;
- break;
-
- case SRCH_BACK:
- *dir = SRCH_FORW;
- redo = TRUE;
- break;
-
- case SRCH_ACCM:
- default:
- *pptr -= 1;
- if (*pptr < 0)
- *pptr = 0;
- pat[*pptr] = '\0';
- break;
- }
- is_pop();
- if (redo) return is_undo(pptr, dir);
- return (TRUE);
- }
-
- is_find(dir) register int dir; {
- register int plen, odoto;
- register LINE *odotp ;
-
- odoto = curwp->w_doto;
- odotp = curwp->w_dotp;
- plen = strlen(pat);
- if (plen != 0) {
- if (dir==SRCH_FORW) {
- (VOID) backchar(TRUE, plen, KRANDOM);
- if (forwsrch() == FALSE) {
- curwp->w_doto = odoto;
- curwp->w_dotp = odotp;
- return (FALSE);
- }
- return (TRUE);
- }
- if (dir==SRCH_BACK) {
- (VOID) forwchar(TRUE, plen, KRANDOM);
- if (backsrch() == FALSE) {
- curwp->w_doto = odoto;
- curwp->w_dotp = odotp;
- return (FALSE);
- }
- return (TRUE);
- }
- ewprintf("bad call to is_find");
- return FALSE;
- }
- return (FALSE);
- }
-
- /*
- * If called with "dir" not one of SRCH_FORW
- * or SRCH_BACK, this routine used to print an error
- * message. It also used to return TRUE or FALSE,
- * depending on if it liked the "dir". However, none
- * of the callers looked at the status, so I just
- * made the checking vanish.
- */
- is_prompt(dir, flag, success) {
- VOID is_dspl();
-
- if (dir == SRCH_FORW) {
- if (success != FALSE)
- is_dspl("I-search", flag);
- else
- is_dspl("Failing I-search", flag);
- } else if (dir == SRCH_BACK) {
- if (success != FALSE)
- is_dspl("I-search backward", flag);
- else
- is_dspl("Failing I-search backward", flag);
- } else ewprintf("Broken call to is_prompt");
- }
-
- /*
- * Prompt writing routine for the incremental search.
- * The "prompt" is just a string. The "flag" determines
- * whether pat should be printed.
- */
- VOID
- is_dspl(prompt, flag) char *prompt; {
-
- if (kbdmop != NULL) return;
- if (flag != FALSE)
- ewprintf("%s: ", prompt);
- else
- ewprintf("%s: %s", prompt, pat);
- }
-
- /*
- * Query Replace.
- * Replace strings selectively. Does a search and replace operation.
- */
- /*ARGSUSED*/
- queryrepl(f, n, k) {
- register int s;
- register int rcnt = 0; /* Replacements made so far */
- register int plen; /* length of found string */
- char news[NPAT]; /* replacement string */
-
- if ((s=readpattern("Query replace")) != TRUE)
- return (s);
- if ((s=ereply("Query replace %s with: ",news, NPAT, pat)) == ABORT)
- return (s);
- if (s == FALSE)
- news[0] = '\0';
- if (kbdmop == NULL) ewprintf("Query replacing %s with %s:", pat, news);
- plen = strlen(pat);
-
- /*
- * Search forward repeatedly, checking each time whether to insert
- * or not. The "!" case makes the check always true, so it gets put
- * into a tighter loop for efficiency.
- */
-
- while (forwsrch() == TRUE) {
- retry:
- update();
- switch (getkey(KQUOTE)) {
- case ' ':
- if (lreplace((RSIZE) plen, news, f) == FALSE)
- return (FALSE);
- rcnt++;
- break;
-
- case '.':
- if (lreplace((RSIZE) plen, news, f) == FALSE)
- return (FALSE);
- rcnt++;
- goto stopsearch;
-
- case CCHR('G'): /* ^G or ESC */
- (VOID) ctrlg(FALSE, 0, KRANDOM);
- case 033:
- goto stopsearch;
-
- case '!':
- do {
- if (lreplace((RSIZE) plen, news, f) == FALSE)
- return (FALSE);
- rcnt++;
- } while (forwsrch() == TRUE);
- goto stopsearch;
-
- case 0x7F: /* To not replace */
- break;
-
- default:
- ewprintf("<SP> replace, [.] rep-end, <DEL> don't, [!] repl rest <ESC> quit");
- goto retry;
- }
- }
- stopsearch:
- curwp->w_flag |= WFHARD;
- update();
- if (kbdmop == NULL) {
- if (rcnt == 0)
- ewprintf("(No replacements done)");
- else if (rcnt == 1)
- ewprintf("(1 replacement done)");
- else
- ewprintf("(%d replacements done)", rcnt);
- }
- return TRUE;
- }
-
- /*
- * This routine does the real work of a
- * forward search. The pattern is sitting in the external
- * variable "pat". If found, dot is updated, the window system
- * is notified of the change, and TRUE is returned. If the
- * string isn't found, FALSE is returned.
- */
- forwsrch() {
- register LINE *clp;
- register int cbo;
- register LINE *tlp;
- register int tbo;
- register char *pp;
- register int c;
-
- clp = curwp->w_dotp;
- cbo = curwp->w_doto;
- while (clp != curbp->b_linep) {
- if (cbo == llength(clp)) {
- clp = lforw(clp);
- cbo = 0;
- c = SEOL;
- } else
- c = lgetc(clp, cbo++);
- if (eq(c, pat[0]) != FALSE) {
- tlp = clp;
- tbo = cbo;
- pp = &pat[1];
- while (*pp != 0) {
- if (tlp == curbp->b_linep)
- goto fail;
- if (tbo == llength(tlp)) {
- tlp = lforw(tlp);
- if (tlp == curbp->b_linep)
- goto fail;
- tbo = 0;
- c = SEOL;
- } else
- c = lgetc(tlp, tbo++);
- if (eq(c, *pp++) == FALSE)
- goto fail;
- }
- curwp->w_dotp = tlp;
- curwp->w_doto = tbo;
- curwp->w_flag |= WFMOVE;
- return (TRUE);
- }
- fail: ;
- }
- return (FALSE);
- }
-
- /*
- * This routine does the real work of a
- * backward search. The pattern is sitting in the external
- * variable "pat". If found, dot is updated, the window system
- * is notified of the change, and TRUE is returned. If the
- * string isn't found, FALSE is returned.
- */
- backsrch() {
- register LINE *clp;
- register int cbo;
- register LINE *tlp;
- register int tbo;
- register int c;
- register char *epp;
- register char *pp;
-
- for (epp = &pat[0]; epp[1] != 0; ++epp)
- ;
- clp = curwp->w_dotp;
- cbo = curwp->w_doto;
- for (;;) {
- if (cbo == 0) {
- clp = lback(clp);
- if (clp == curbp->b_linep)
- return (FALSE);
- cbo = llength(clp)+1;
- }
- if (--cbo == llength(clp))
- c = SEOL;
- else
- c = lgetc(clp,cbo);
- if (eq(c, *epp) != FALSE) {
- tlp = clp;
- tbo = cbo;
- pp = epp;
- while (pp != &pat[0]) {
- if (tbo == 0) {
- tlp = lback(tlp);
- if (tlp == curbp->b_linep)
- goto fail;
- tbo = llength(tlp)+1;
- }
- if (--tbo == llength(tlp))
- c = SEOL;
- else
- c = lgetc(tlp,tbo);
- if (eq(c, *--pp) == FALSE)
- goto fail;
- }
- curwp->w_dotp = tlp;
- curwp->w_doto = tbo;
- curwp->w_flag |= WFMOVE;
- return (TRUE);
- }
- fail: ;
- }
- }
-
- /*
- * Compare two characters.
- * The "bc" comes from the buffer.
- * It has its case folded out. The
- * "pc" is from the pattern.
- */
- eq(bc, pc) {
- register int ibc;
- register int ipc;
-
- ibc = bc & 0xFF;
- ipc = pc & 0xFF;
- if (ISLOWER(ibc) != FALSE)
- ibc = TOUPPER(ibc);
- if (ISLOWER(ipc) != FALSE)
- ipc = TOUPPER(ipc);
- if (ibc == ipc)
- return (TRUE);
- return (FALSE);
- }
-
- /*
- * Read a pattern.
- * Stash it in the external variable "pat". The "pat" is
- * not updated if the user types in an empty line. If the user typed
- * an empty line, and there is no old pattern, it is an error.
- * Display the old pattern, in the style of Jeff Lomicka. There is
- * some do-it-yourself control expansion.
- */
- readpattern(prompt) char *prompt; {
- register int s;
- char tpat[NPAT];
-
- if (tpat[0] == '\0') s = ereply("%s: ", tpat, NPAT, prompt);
- else s = ereply("%s: (default %s) ", tpat, NPAT, prompt, pat);
-
- if (s == TRUE) /* Specified */
- (VOID) strcpy(pat, tpat);
- else if (s==FALSE && pat[0]!=0) /* CR, but old one */
- s = TRUE;
- return (s);
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'symbol.c'
- then
- echo shar: will not over-write existing file "'symbol.c'"
- else
- cat << \SHAR_EOF > 'symbol.c'
- /*
- * Symbol tables, and keymap setup.
- * The terminal specific parts of building the
- * keymap has been moved to a better place.
- */
- #include "def.h"
-
- #ifdef HASH
- Since you're seeing this, you must have defined HASH to try and get the
- hashing code back. You're getting an error because I (mwm@ucbvax) want you
- to read this.
-
- With the change in function completion, there is at least one linear search
- through the function list for every hash lookup (ignoring the startup code).
- Given that there are probably actually MANY more linear searches for
- completion than fullname lookups, some structure other than a hash table is
- better suited to this purpose. I suggest trying sorting the lists for more
- speed, then going to a binary search tree, and finally going to a trie.
- #endif HASH
-
- /*
- * Defined here so to collect the #ifdef MEYN config stuff in one file
- * If you set either MINDENT or MFILL, then you need to change the bindings
- * in this file to match: KCTRL|'M' -> newline-and-indent and KCTRL|'J' ->
- * insert-newline for MINDENT, and ' ' -> insert-with-wrap for MFILL.
- * MEYN is used for compile-time customization of the system for micros.
- */
- #ifndef MEYN
- int mode = 0; /* All modes off */
- #else
- int mode = MBSMAP|MINDENT;
- #endif
-
- /*
- * Defined by "main.c".
- */
- extern int ctrlg(); /* Abort out of things */
- extern int quit(); /* Quit */
- extern int ctlxlp(); /* Begin macro */
- extern int ctlxrp(); /* End macro */
- extern int ctlxe(); /* Execute macro */
- extern int showversion(); /* Show version numbers, etc. */
-
- /*
- * Defined by "search.c".
- */
- extern int forwsearch(); /* Search forward */
- extern int backsearch(); /* Search backwards */
- extern int searchagain(); /* Repeat last search command */
- extern int forwisearch(); /* Incremental search forward */
- extern int backisearch(); /* Incremental search backwards */
- extern int queryrepl(); /* Query replace */
-
- /*
- * Defined by "basic.c".
- */
- extern int gotobol(); /* Move to start of line */
- extern int backchar(); /* Move backward by characters */
- extern int gotoeol(); /* Move to end of line */
- extern int forwchar(); /* Move forward by characters */
- extern int gotobob(); /* Move to start of buffer */
- extern int gotoeob(); /* Move to end of buffer */
- extern int forwline(); /* Move forward by lines */
- extern int backline(); /* Move backward by lines */
- extern int forwpage(); /* Move forward by pages */
- extern int backpage(); /* Move backward by pages */
- extern int pagenext(); /* Page forward next window */
- extern int setmark(); /* Set mark */
- extern int swapmark(); /* Swap "." and mark */
- extern int gotoline(); /* Go to a specified line. */
-
- /*
- * Defined by "buffer.c".
- */
- extern int listbuffers(); /* Display list of buffers */
- extern int usebuffer(); /* Switch a window to a buffer */
- extern int poptobuffer(); /* Other window to a buffer */
- extern int killbuffer(); /* Make a buffer go away. */
- extern int savebuffers(); /* Save unmodified buffers */
- extern int bufferinsert(); /* Insert buffer into another */
- extern int notmodified(); /* Reset modification flag */
-
- #ifdef DIRLIST
- /*
- * Defined by "dirlist.c".
- */
- extern int dirlist(); /* Directory list. */
- #endif
-
- /*
- * Defined by "file.c".
- */
- extern int filevisit(); /* Get a file, read write */
- extern int poptofile(); /* Get a file, other window */
- extern int filewrite(); /* Write a file */
- extern int filesave(); /* Save current file */
- extern int fileinsert(); /* Insert file into buffer */
-
- /*
- * Defined by "match.c"
- */
- extern int blinkparen(); /* Fake blink-matching-paren var */
- extern int showmatch(); /* Hack to show matching paren */
-
- /*
- * Defined by "random.c".
- */
- extern int selfinsert(); /* Insert character */
- extern int showcpos(); /* Show the cursor position */
- extern int twiddle(); /* Twiddle characters */
- extern int quote(); /* Insert literal */
- extern int openline(); /* Open up a blank line */
- extern int newline(); /* Insert CR-LF */
- extern int deblank(); /* Delete blank lines */
- extern int delwhite(); /* Delete extra whitespace */
- extern int indent(); /* Insert CR-LF, then indent */
- extern int forwdel(); /* Forward delete */
- extern int backdel(); /* Backward delete in */
- extern int killline(); /* Kill forward */
- extern int yank(); /* Yank back from killbuffer. */
- extern int bsmapmode(); /* set bsmap mode */
- extern int flowmode(); /* set flow mode */
- extern int indentmode(); /* set auto-indent mode */
- extern int fillmode(); /* set word-wrap mode */
-
- /*
- * Defined by "region.c".
- */
- extern int killregion(); /* Kill region. */
- extern int copyregion(); /* Copy region to kill buffer. */
- extern int lowerregion(); /* Lower case region. */
- extern int upperregion(); /* Upper case region. */
- #ifdef PREFIXREGION
- extern int prefixregion(); /* Prefix all lines in region */
- extern int setprefix(); /* Set line prefix string */
- #endif
-
- /*
- * Defined by "spawn.c".
- */
- extern int spawncli(); /* Run CLI in a subjob. */
- #ifdef VMS
- extern int attachtoparent(); /* Attach to parent process */
- #endif
-
- /*
- * Defined by "window.c".
- */
- extern int reposition(); /* Reposition window */
- extern int refresh(); /* Refresh the screen */
- extern int nextwind(); /* Move to the next window */
- extern int prevwind(); /* Move to the previous window */
- extern int onlywind(); /* Make current window only one */
- extern int splitwind(); /* Split current window */
- extern int delwind(); /* Delete current window */
- extern int enlargewind(); /* Enlarge display window. */
- extern int shrinkwind(); /* Shrink window. */
-
- /*
- * Defined by "word.c".
- */
- extern int backword(); /* Backup by words */
- extern int forwword(); /* Advance by words */
- extern int upperword(); /* Upper case word. */
- extern int lowerword(); /* Lower case word. */
- extern int capword(); /* Initial capitalize word. */
- extern int delfword(); /* Delete forward word. */
- extern int delbword(); /* Delete backward word. */
-
- /*
- * Defined by "extend.c".
- */
- extern int extend(); /* Extended commands. */
- extern int desckey(); /* Help key. */
- extern int bindtokey(); /* Modify key bindings. */
- extern int unsetkey(); /* Unbind a key. */
- extern int wallchart(); /* Make wall chart. */
- #ifdef STARTUP
- extern int evalexpr(); /* Extended commands (again) */
- extern int evalbuffer(); /* Evaluate current buffer */
- extern int evalfile(); /* Evaluate a file */
- #endif
-
- /*
- * defined by "paragraph.c" - the paragraph justification code.
- */
- extern int gotobop(); /* Move to start of paragraph. */
- extern int gotoeop(); /* Move to end of paragraph. */
- extern int fillpara(); /* Justify a paragraph. */
- extern int killpara(); /* Delete a paragraph. */
- extern int setfillcol(); /* Set fill column for justify. */
- extern int fillword(); /* Insert char with word wrap. */
-
- /*
- * defined by prefix.c
- */
- extern int help(); /* Parse help key. */
- extern int ctlx4hack(); /* Parse a pop-to key. */
-
- typedef struct {
- KEY k_key; /* Key to bind. */
- int (*k_funcp)(); /* Function. */
- char *k_name; /* Function name string. */
- } KEYTAB;
-
- /*
- * Default key binding table. This contains
- * the function names, the symbol table name, and (possibly)
- * a key binding for the builtin functions. There are no
- * bindings for C-U or C-X. These are done with special
- * code, but should be done normally.
- */
- KEYTAB key[] = {
- #ifdef MEYN /* Add meyer's peculiar bindings */
- KCTRL|'J', newline, "insert-newline",
- KCTRL|'M', indent, "newline-and-indent",
- KCTLX|'N', nextwind, "next-window",
- KCTLX|'P', prevwind, "previous-window",
- KMETA|KCTRL|'C',quit, "save-buffers-kill-emacs",
- KMETA|KCTRL|'L',refresh, "redraw-display",
- KMETA|'G', gotoline, "goto-line",
- KMETA|'J', fillpara, "fill-paragraph",
- KMETA|'Q', queryrepl, "query-replace",
- #endif
- KCTRL|'@', setmark, "set-mark-command",
- KCTRL|'A', gotobol, "beginning-of-line",
- KCTRL|'B', backchar, "backward-char",
- KCTRL|'D', forwdel, "delete-char",
- KCTRL|'E', gotoeol, "end-of-line",
- KCTRL|'F', forwchar, "forward-char",
- KCTRL|'G', ctrlg, "keyboard-quit",
- KCTRL|'H', help, "help",
- KCTRL|'I', selfinsert, "self-insert-command",
- #ifndef MEYN
- KCTRL|'J', indent, "newline-and-indent",
- #endif
- KCTRL|'L', reposition, "recenter",
- KCTRL|'K', killline, "kill-line",
- #ifndef MEYN
- KCTRL|'M', newline, "insert-newline",
- #endif
- KCTRL|'N', forwline, "next-line",
- KCTRL|'O', openline, "open-line",
- KCTRL|'P', backline, "previous-line",
- KCTRL|'Q', quote, "quoted-insert",
- KCTRL|'R', backisearch, "isearch-backward",
- KCTRL|'S', forwisearch, "isearch-forward",
- KCTRL|'T', twiddle, "transpose-chars",
- KCTRL|'V', forwpage, "scroll-up",
- KCTRL|'W', killregion, "kill-region",
- KCTRL|'Y', yank, "yank",
- #ifdef VMS
- KCTRL|'Z', attachtoparent, "suspend-emacs",
- #else
- KCTRL|'Z', spawncli, "suspend-emacs",
- #endif
- KCTLX|KCTRL|'B',listbuffers, "list-buffers",
- #ifndef MEYN
- KCTLX|KCTRL|'C',quit, "save-buffers-kill-emacs",
- #endif
- #ifdef DIRLIST
- KCTLX|KCTRL|'D',dirlist, "display-directory",
- #endif
- KCTLX|KCTRL|'F',filevisit, "find-file",
- KCTLX|KCTRL|'L',lowerregion, "downcase-region",
- KCTLX|KCTRL|'O',deblank, "delete-blank-lines",
- KCTLX|KCTRL|'S',filesave, "save-buffer",
- KCTLX|KCTRL|'U',upperregion, "upcase-region",
- KCTLX|KCTRL|'W',filewrite, "write-file",
- KCTLX|KCTRL|'X',swapmark, "exchange-point-and-mark",
- KCTLX|'=', showcpos, "what-cursor-position",
- KCTLX|'(', ctlxlp, "start-kbd-macro",
- KCTLX|')', ctlxrp, "end-kbd-macro",
- KCTLX|'^', enlargewind, "enlarge-window",
- KCTLX|'0', delwind, "delete-window",
- KCTLX|'1', onlywind, "delete-other-windows",
- KCTLX|'2', splitwind, "split-window-vertically",
- KCTLX|'4', ctlx4hack, "ctrlx-four-hack",
- KCTLX|'B', usebuffer, "switch-to-buffer",
- KCTLX|'E', ctlxe, "call-last-kbd-macro",
- KCTLX|'F', setfillcol, "set-fill-column",
- KCTLX|'I', fileinsert, "insert-file",
- KCTLX|'K', killbuffer, "kill-buffer",
- KCTLX|'S', savebuffers, "save-some-buffers",
- #ifndef MEYN
- KCTLX|'O', nextwind, "next-window",
- KMETA|'%', queryrepl, "query-replace",
- #endif
- KMETA|KCTRL|'V',pagenext, "scroll-other-window",
- KMETA|'>', gotoeob, "end-of-buffer",
- KMETA|'<', gotobob, "beginning-of-buffer",
- KMETA|'[', gotobop, "backward-paragraph",
- KMETA|']', gotoeop, "forward-paragraph",
- KMETA|' ', delwhite, "just-one-space",
- KMETA|'B', backword, "backward-word",
- KMETA|'C', capword, "capitalize-word",
- KMETA|'D', delfword, "kill-word",
- KMETA|'F', forwword, "forward-word",
- KMETA|'L', lowerword, "downcase-word",
- #ifndef MEYN
- KMETA|'Q', fillpara, "fill-paragraph",
- #endif
- KMETA|'R', backsearch, "search-backward",
- KMETA|'S', forwsearch, "search-forward",
- KMETA|'U', upperword, "upcase-word",
- KMETA|'V', backpage, "scroll-down",
- KMETA|'W', copyregion, "copy-region-as-kill",
- KMETA|'X', extend, "execute-extended-command",
- KMETA|'~', notmodified, "not-modified",
- #ifndef MEYN
- -1, prevwind, "previous-window",
- -1, refresh, "redraw-display",
- -1, gotoline, "goto-line",
- #endif
- #ifdef STARTUP
- -1, evalexpr, "eval-expression",
- -1, evalbuffer, "eval-current-buffer",
- -1, evalfile, "load",
- #endif
- -1, bsmapmode, "bsmap-mode",
- -1, flowmode, "flow-mode",
- -1, indentmode, "auto-indent-mode",
- -1, fillmode, "auto-fill-mode",
- -1, fillword, "insert-with-wrap",
- -1, shrinkwind, "shrink-window",
- -1, searchagain, "search-again",
- -1, unsetkey, "global-unset-key",
- -1, bindtokey, "global-set-key",
- -1, killpara, "kill-paragraph",
- -1, showversion, "emacs-version",
- -1, blinkparen, "blink-matching-paren",
- -1, showmatch, "blink-matching-paren-hack",
- -1, bufferinsert, "insert-buffer",
- #ifdef VMS
- -1, spawncli, "push-to-dcl",
- #endif
- #ifdef PREFIXREGION
- -1, prefixregion, "prefix-region",
- -1, setprefix, "set-prefix-string",
- #endif
- /* You can actually get to these with keystrokes. See prefix.c */
- -1, poptobuffer, "switch-to-buffer-other-window",
- -1, poptofile, "find-file-other-window",
- -1, desckey, "describe-key-briefly",
- -1, wallchart, "describe-bindings",
- };
-
- #define NKEY (sizeof(key) / sizeof(key[0]))
-
- /*
- * Symbol table lookup.
- * Return a pointer to the SYMBOL node, or NULL if
- * the symbol is not found.
- */
- SYMBOL *
- symlookup(cp) register char *cp; {
- register SYMBOL *sp;
-
- #ifdef HASH
- sp = symbol[symhash(cp)];
- #else
- sp = symbol[0];
- #endif
- while (sp != NULL) {
- if (strcmp(cp, sp->s_name) == 0)
- return (sp);
- #ifdef HASH
- if ((sp->s_flags&SFEND) != 0) break;
- #endif
- sp = sp->s_symp;
- }
- return (NULL);
- }
-
- #ifdef HASH
- /*
- * Take a string, and compute the symbol table
- * bucket number. This is done by adding all of the characters
- * together, and taking the sum mod NSHASH. The string probably
- * should not contain any GR characters; if it does the "*cp"
- * may get a nagative number on some machines, and the "%"
- * will return a negative number!
- */
- symhash(cp) register char *cp; {
- register int c;
- register int n;
-
- n = 0;
- while ((c = *cp++) != 0)
- n += c;
- return (n % NSHASH);
- }
- #endif
-
- /*
- * Build initial keymap. The funny keys
- * (commands, odd control characters) are mapped using
- * a big table and calls to "keyadd". The printing characters
- * are done with some do-it-yourself handwaving. The terminal
- * specific keymap initialization code is called at the
- * very end to finish up. All errors are fatal.
- */
- keymapinit() {
- register SYMBOL *sp;
- register KEYTAB *kp;
- register int i;
-
- for (i=0; i<NKEYS; ++i)
- binding[i] = NULL;
- for (kp = &key[0]; kp < &key[NKEY]; ++kp)
- keyadd(kp->k_key, kp->k_funcp, kp->k_name);
- keydup((KEY) (KCTLX|KCTRL|'G'), "keyboard-quit");
- keydup((KEY) (KMETA|KCTRL|'G'), "keyboard-quit");
- keyadd((KEY) (KMETA|0x7F), delbword,
- "backward-kill-word");
- keyadd((KEY) 0x7F, backdel, "backward-delete-char");
- /*
- * add duplicates (GNU-stuff)
- */
- keydup((KEY) (KCTLX|KCTRL|'Z'), "suspend-emacs");
- /*
- * Should be bound by "tab" already.
- */
- if ((sp=symlookup("self-insert-command")) == NULL)
- panic("no self-insert-command in keymapinit");
- for (i=0x20; i<0x7F; ++i) {
- if (binding[i] != NULL)
- panic("nonull binding in keymapinit");
- binding[i] = sp;
- }
- ttykeymapinit();
- #ifdef HASH
- /* Link up the symbol table entries */
- for (sp = symbol[i = 0]; i < NSHASH-1; sp = sp->s_symp)
- if (sp->s_symp == NULL) sp->s_symp = symbol[++i];
- #endif
- }
-
- /*
- * Create a new builtin function "name"
- * with function "funcp". If the "new" is a real
- * key, bind it as a side effect. All errors
- * are fatal.
- */
- keyadd(new, funcp, name) register KEY new; int (*funcp)(); char *name; {
- register SYMBOL *sp;
- #ifdef HASH
- register int hash;
- #endif
-
- if ((sp=(SYMBOL *)malloc(sizeof(SYMBOL))) == NULL)
- panic("No memory");
- #ifdef HASH
- hash = symhash(name);
- if (symbol[hash] == NULL) sp->s_flags |= SFEND;
- sp->s_symp = symbol[hash];
- symbol[hash] = sp;
- #else
- sp->s_symp = symbol[0];
- symbol[0] = sp;
- #endif
- sp->s_name = name;
- sp->s_funcp = funcp;
- if (new >= 0) { /* Bind this key. */
- if (binding[new] != NULL)
- panic("rebinding old symbol");
- binding[new] = sp;
- }
- }
-
- /*
- * Bind key "new" to the existing
- * routine "name". If the name cannot be found,
- * or the key is already bound, abort.
- */
- keydup(new, name) register KEY new; char *name; {
- register SYMBOL *sp;
-
- if (binding[new]!=NULL || (sp=symlookup(name))==NULL) {
- #ifdef KEYDUP_ERROR
- fprintf (stderr, "keydup: binding[%d] = %x",
- new, binding[new]);
- fprintf (stderr, " and symlookup(%s) == %x\n", name, sp);
- #endif
- panic("keydup");
- }
- binding[new] = sp;
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'window.c'
- then
- echo shar: will not over-write existing file "'window.c'"
- else
- cat << \SHAR_EOF > 'window.c'
- /*
- * Window handling.
- */
- #include "def.h"
-
- /*
- * Reposition dot in the current
- * window to line "n". If the argument is
- * positive, it is that line. If it is negative it
- * is that line from the bottom. If it is 0 the window
- * is centered (this is what the standard redisplay code
- * does). If GOSREC is undefined, default is 0, so it acts like GNU.
- * If GOSREC is defined, with no argument it defaults to 1
- * and works like in Gosling.
- */
- /*ARGSUSED*/
- reposition(f, n, k) {
- #ifndef GOSREC
- curwp->w_force = ((f == FALSE) ? 0 : n) ;
- #else
- curwp->w_force = n;
- #endif
- curwp->w_flag |= WFFORCE;
- sgarbf = TRUE;
- return (TRUE);
- }
-
- /*
- * Refresh the display. A call is made to the
- * "ttresize" entry in the terminal handler, which tries
- * to reset "nrow" and "ncol". They will, however, never
- * be set outside of the NROW or NCOL range. If the display
- * changed size, arrange that everything is redone, then
- * call "update" to fix the display. We do this so the
- * new size can be displayed. In the normal case the
- * call to "update" in "main.c" refreshes the screen,
- * and all of the windows need not be recomputed.
- * Note that when you get to the "display unusable"
- * message, the screen will be messed up. If you make
- * the window bigger again, and send another command,
- * everything will get fixed!
- */
- /*ARGSUSED*/
- refresh(f, n, k) {
- register WINDOW *wp;
- register int oldnrow;
- register int oldncol;
-
- oldnrow = nrow;
- oldncol = ncol;
- ttresize();
- if (nrow!=oldnrow || ncol!=oldncol) {
- wp = wheadp; /* Find last. */
- while (wp->w_wndp != NULL)
- wp = wp->w_wndp;
- if (nrow < wp->w_toprow+3) { /* Check if too small. */
- ewprintf("Display unusable");
- return (FALSE);
- }
- wp->w_ntrows = nrow-wp->w_toprow-2;
- sgarbf = TRUE;
- update();
- if (kbdmop == NULL) ewprintf("New size %d by %d", nrow, ncol);
- } else
- sgarbf = TRUE;
- return (TRUE);
- }
-
- /*
- * The command to make the next
- * window (next => down the screen)
- * the current window. There are no real
- * errors, although the command does
- * nothing if there is only 1 window on
- * the screen.
- */
- /*ARGSUSED*/
- nextwind(f, n, k) {
- register WINDOW *wp;
-
- if ((wp=curwp->w_wndp) == NULL)
- wp = wheadp;
- curwp = wp;
- curbp = wp->w_bufp;
- return (TRUE);
- }
-
- /*
- * This command makes the previous
- * window (previous => up the screen) the
- * current window. There arn't any errors,
- * although the command does not do a lot
- * if there is 1 window.
- */
- /*ARGSUSED*/
- prevwind(f, n, k) {
- register WINDOW *wp1;
- register WINDOW *wp2;
-
- wp1 = wheadp;
- wp2 = curwp;
- if (wp1 == wp2)
- wp2 = NULL;
- while (wp1->w_wndp != wp2)
- wp1 = wp1->w_wndp;
- curwp = wp1;
- curbp = wp1->w_bufp;
- return (TRUE);
- }
-
- /*
- * This command makes the current
- * window the only window on the screen.
- * Try to set the framing
- * so that "." does not have to move on
- * the display. Some care has to be taken
- * to keep the values of dot and mark
- * in the buffer structures right if the
- * distruction of a window makes a buffer
- * become undisplayed.
- */
- /*ARGSUSED*/
- onlywind(f, n, k) {
- register WINDOW *wp;
- register LINE *lp;
- register int i;
-
- while (wheadp != curwp) {
- wp = wheadp;
- wheadp = wp->w_wndp;
- if (--wp->w_bufp->b_nwnd == 0) {
- wp->w_bufp->b_dotp = wp->w_dotp;
- wp->w_bufp->b_doto = wp->w_doto;
- wp->w_bufp->b_markp = wp->w_markp;
- wp->w_bufp->b_marko = wp->w_marko;
- }
- free((char *) wp);
- }
- while (curwp->w_wndp != NULL) {
- wp = curwp->w_wndp;
- curwp->w_wndp = wp->w_wndp;
- if (--wp->w_bufp->b_nwnd == 0) {
- wp->w_bufp->b_dotp = wp->w_dotp;
- wp->w_bufp->b_doto = wp->w_doto;
- wp->w_bufp->b_markp = wp->w_markp;
- wp->w_bufp->b_marko = wp->w_marko;
- }
- free((char *) wp);
- }
- lp = curwp->w_linep;
- i = curwp->w_toprow;
- while (i!=0 && lback(lp)!=curbp->b_linep) {
- --i;
- lp = lback(lp);
- }
- curwp->w_toprow = 0;
- curwp->w_ntrows = nrow-2; /* 2 = mode, echo. */
- curwp->w_linep = lp;
- curwp->w_flag |= WFMODE|WFHARD;
- return (TRUE);
- }
-
- /*
- * Split the current window. A window
- * smaller than 3 lines cannot be split.
- * The only other error that is possible is
- * a "malloc" failure allocating the structure
- * for the new window.
- */
- /*ARGSUSED*/
- splitwind(f, n, k) {
- register WINDOW *wp;
- register LINE *lp;
- register int ntru;
- register int ntrd;
- int ntrl;
- WINDOW *wp1, *wp2;
-
- if (curwp->w_ntrows < 3) {
- ewprintf("Cannot split a %d line window", curwp->w_ntrows);
- return (FALSE);
- }
- if ((wp = (WINDOW *)malloc(sizeof(WINDOW))) == NULL) {
- ewprintf("Can't get %d", sizeof(WINDOW));
- return (FALSE);
- }
- ++curbp->b_nwnd; /* Displayed twice. */
- wp->w_bufp = curbp;
- wp->w_dotp = curwp->w_dotp;
- wp->w_doto = curwp->w_doto;
- wp->w_markp = curwp->w_markp;
- wp->w_marko = curwp->w_marko;
- wp->w_flag = 0;
- wp->w_force = 0;
- ntru = (curwp->w_ntrows-1) / 2; /* Upper size */
- ntrl = (curwp->w_ntrows-1) - ntru; /* Lower size */
- lp = curwp->w_linep;
- ntrd = 0;
- while (lp != curwp->w_dotp) {
- ++ntrd;
- lp = lforw(lp);
- }
- lp = curwp->w_linep;
- if (ntrd <= ntru) { /* Old is upper window. */
- if (ntrd == ntru) /* Hit mode line. */
- lp = lforw(lp);
- curwp->w_ntrows = ntru;
- wp->w_wndp = curwp->w_wndp;
- curwp->w_wndp = wp;
- wp->w_toprow = curwp->w_toprow+ntru+1;
- wp->w_ntrows = ntrl;
- } else { /* Old is lower window */
- wp1 = NULL;
- wp2 = wheadp;
- while (wp2 != curwp) {
- wp1 = wp2;
- wp2 = wp2->w_wndp;
- }
- if (wp1 == NULL)
- wheadp = wp;
- else
- wp1->w_wndp = wp;
- wp->w_wndp = curwp;
- wp->w_toprow = curwp->w_toprow;
- wp->w_ntrows = ntru;
- ++ntru; /* Mode line. */
- curwp->w_toprow += ntru;
- curwp->w_ntrows = ntrl;
- while (ntru--)
- lp = lforw(lp);
- }
- curwp->w_linep = lp; /* Adjust the top lines */
- wp->w_linep = lp; /* if necessary. */
- curwp->w_flag |= WFMODE|WFHARD;
- wp->w_flag |= WFMODE|WFHARD;
- return (TRUE);
- }
-
- /*
- * Enlarge the current window.
- * Find the window that loses space. Make
- * sure it is big enough. If so, hack the window
- * descriptions, and ask redisplay to do all the
- * hard work. You don't just set "force reframe"
- * because dot would move.
- */
- /*ARGSUSED*/
- enlargewind(f, n, k) {
- register WINDOW *adjwp;
- register LINE *lp;
- register int i;
-
- if (n < 0)
- return (shrinkwind(f, -n, KRANDOM));
- if (wheadp->w_wndp == NULL) {
- ewprintf("Only one window");
- return (FALSE);
- }
- if ((adjwp=curwp->w_wndp) == NULL) {
- adjwp = wheadp;
- while (adjwp->w_wndp != curwp)
- adjwp = adjwp->w_wndp;
- }
- if (adjwp->w_ntrows <= n) {
- ewprintf("Impossible change");
- return (FALSE);
- }
- if (curwp->w_wndp == adjwp) { /* Shrink below. */
- lp = adjwp->w_linep;
- for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
- lp = lforw(lp);
- adjwp->w_linep = lp;
- adjwp->w_toprow += n;
- } else { /* Shrink above. */
- lp = curwp->w_linep;
- for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
- lp = lback(lp);
- curwp->w_linep = lp;
- curwp->w_toprow -= n;
- }
- curwp->w_ntrows += n;
- adjwp->w_ntrows -= n;
- curwp->w_flag |= WFMODE|WFHARD;
- adjwp->w_flag |= WFMODE|WFHARD;
- return (TRUE);
- }
-
- /*
- * Shrink the current window.
- * Find the window that gains space. Hack at
- * the window descriptions. Ask the redisplay to
- * do all the hard work.
- */
- shrinkwind(f, n, k) {
- register WINDOW *adjwp;
- register LINE *lp;
- register int i;
-
- if (n < 0)
- return (enlargewind(f, -n, KRANDOM));
- if (wheadp->w_wndp == NULL) {
- ewprintf("Only one window");
- return (FALSE);
- }
- /*
- * Bit of flakiness - KRANDOM means it was an internal call, and
- * to be trusted implicitly about sizes.
- */
- if (k != KRANDOM && curwp->w_ntrows <= n) {
- ewprintf("Impossible change");
- return (FALSE);
- }
- if ((adjwp=curwp->w_wndp) == NULL) {
- adjwp = wheadp;
- while (adjwp->w_wndp != curwp)
- adjwp = adjwp->w_wndp;
- }
- if (curwp->w_wndp == adjwp) { /* Grow below. */
- lp = adjwp->w_linep;
- for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
- lp = lback(lp);
- adjwp->w_linep = lp;
- adjwp->w_toprow -= n;
- } else { /* Grow above. */
- lp = curwp->w_linep;
- for (i=0; i<n && lp!=curbp->b_linep; ++i)
- lp = lforw(lp);
- curwp->w_linep = lp;
- curwp->w_toprow += n;
- }
- curwp->w_ntrows -= n;
- adjwp->w_ntrows += n;
- curwp->w_flag |= WFMODE|WFHARD;
- adjwp->w_flag |= WFMODE|WFHARD;
- return (TRUE);
- }
-
- /*
- * Delete current window. Call shrink-window to do the screen
- * updating, then throw away the window.
- */
- /*ARGSUSED*/
- delwind(f, n, k) {
- register WINDOW *wp, *nwp;
-
- wp = curwp; /* Cheap... */
- /* shrinkwind returning false means only one window... */
- if (shrinkwind(FALSE, wp->w_ntrows + 1, KRANDOM) == FALSE)
- return FALSE;
- if (--wp->w_bufp->b_nwnd == 0) {
- wp->w_bufp->b_dotp = wp->w_dotp;
- wp->w_bufp->b_doto = wp->w_doto;
- wp->w_bufp->b_markp = wp->w_markp;
- wp->w_bufp->b_marko = wp->w_marko;
- }
- /* since shrinkwind did't crap out, we know we have a second window */
- if (wp == wheadp) wheadp = curwp = wp->w_wndp;
- else if ((curwp = wp->w_wndp) == NULL) curwp = wheadp;
- curbp = curwp->w_bufp;
- for (nwp = wheadp; nwp != NULL; nwp = nwp->w_wndp)
- if (nwp->w_wndp == wp) {
- nwp->w_wndp = wp->w_wndp;
- break ;
- }
- free((char *) wp);
- return TRUE;
- }
- /*
- * Pick a window for a pop-up.
- * Split the screen if there is only
- * one window. Pick the uppermost window that
- * isn't the current window. An LRU algorithm
- * might be better. Return a pointer, or
- * NULL on error.
- */
- WINDOW *
- wpopup() {
- register WINDOW *wp;
-
- if (wheadp->w_wndp == NULL
- && splitwind(FALSE, 0, KRANDOM) == FALSE)
- return (NULL);
- wp = wheadp; /* Find window to use */
- while (wp!=NULL && wp==curwp)
- wp = wp->w_wndp;
- return (wp);
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'tty/termcap/tty.c'
- then
- echo shar: will not over-write existing file "'tty/termcap/tty.c'"
- else
- cat << \SHAR_EOF > 'tty/termcap/tty.c'
- /*
- * Termcap/terminfo display driver
- *
- * Termcap is a terminal information database and routines to describe
- * terminals on most UNIX systems. Many other systems have adopted
- * this as a reasonable way to allow for widly varying and ever changing
- * varieties of terminal types. This should be used where practical.
- */
- /* Known problems:
- * tputs is always called with the number of lines affected set to
- * one. Therefore, padding may be insufficient on some sequences
- * dispite termcap being set up correctly.
- *
- * If you have a terminal with no clear to end of screen and
- * memory of lines below the ones visible on the screen, display
- * will be wrong in some cases. I doubt that any such terminal
- * was ever made, but I thought everyone with delete line would
- * have clear to end of screen too...
- *
- * Code for terminals without clear to end of screen and/or clear
- * to end of line has not been extensivly tested.
- *
- * Cost calculations are very rough. Costs of insert/delete line
- * may be far from the truth. This is accentuated by display.c
- * not knowing about multi-line insert/delete.
- *
- * Using scrolling region vs insert/delete line should probably
- * be based on cost rather than the assuption that scrolling
- * region operations look better.
- */
- #include "def.h"
-
- #define BEL 0x07 /* BEL character. */
- #define LF 0x0A /* Line feed. */
-
- extern int ttrow;
- extern int ttcol;
- extern int tttop;
- extern int ttbot;
- extern int tthue;
-
- int tceeol; /* Costs are set later */
- int tcinsl;
- int tcdell;
-
- static int insdel; /* Do we have both insert & delete line? */
-
- char *tgetstr();
- char *tgoto();
- int ttputc();
-
- #define TCAPSLEN 1024
-
- char tcapbuf[TCAPSLEN];
-
- /* PC, UP, and BC are used by termlib, so must be extern and have these
- * names unless you have a non-standard termlib.
- */
-
- int LI; /* standard # lines */
- char PC,
- *CM,
- *CE,
- *UP,
- *BC,
- *IM, /* insert mode */
- *IC, /* insert a single space */
- *EI, /* end insert mode */
- *DC,
- *AL, /* add line */
- *DL, /* del line */
- *pAL, /* parameterized add line */
- *pDL, /* parameterized delete line */
- *TI, /* term init -- start using cursor motion */
- *TE, /* term end --- end using cursor motion */
- *SO,
- *SE,
- *CD,
- *CS, /* set scroll region */
- *SR; /* back index (used with scroll region */
- #ifdef XKEYS
- char *K[NFKEYS], /* other function key codes */
- *L[NFKEYS], /* labels for other functions keys */
- *KS, *KE, /* enter keypad mode, exit keypad mode */
- *KH, *KU, *KD, *KL, *KR; /* home, arrow keys */
- #endif
- int SG; /* number of glitches, 0 for invisable, -1 for none */
- /* (yes virginia, there are terminals with invisible glitches) */
-
- /*
- * Initialize the terminal when the editor
- * gets started up.
- */
- static char tcbuf[1024];
-
- ttinit() {
- char *getenv();
- char *t, *p, *tgetstr();
- char *tv_stype;
- #ifdef XKEYS
- char kname[3], lname[3];
- int i;
- #endif
-
- #ifdef VAXC
- if ((tv_stype = trnlnm("TERM")) == NULL)
- #else
- if ((tv_stype = getenv("TERM")) == NULL)/* Don't want VAX C getenv() */
- #endif
- panic("Environment variable TERM not defined!");
-
- if((tgetent(tcbuf, tv_stype)) != 1)
- {
- (VOID) strcpy(tcbuf, "Unknown terminal type ");
- (VOID) strcat(tcbuf, tv_stype);
- panic(tcbuf);
- }
-
- p = tcapbuf;
- t = tgetstr("pc", &p);
- if(t) PC = *t;
-
- LI = tgetnum("li");
- CD = tgetstr("cd", &p);
- CM = tgetstr("cm", &p);
- CE = tgetstr("ce", &p);
- UP = tgetstr("up", &p);
- BC = tgetstr("bc", &p);
- IM = tgetstr("im", &p);
- IC = tgetstr("ic", &p);
- EI = tgetstr("ei", &p);
- DC = tgetstr("dc", &p);
- AL = tgetstr("al", &p);
- DL = tgetstr("dl", &p);
- pAL= tgetstr("AL", &p); /* parameterized insert and del. line */
- pDL= tgetstr("DL", &p);
- TI = tgetstr("ti", &p);
- TE = tgetstr("te", &p);
- SO = tgetstr("so", &p);
- SE = tgetstr("se", &p);
- CS = tgetstr("cs", &p); /* set scrolling region */
- SR = tgetstr("sr", &p);
- SG = tgetnum("sg"); /* standout glitch */
- #ifdef XKEYS
- /* get the 10 standard termcap keys */
- strcpy(kname,"kx");
- strcpy(lname,"lx");
- for (i = 0; i < 10; i++) {
- kname[1] = i + '0';
- K[i] = tgetstr(kname, &p);
- lname[1] = i + '0';
- L[i] = tgetstr(lname, &p);
- }
- /* Hack to get another bunch */
- strcpy(kname,"Kx");
- strcpy(lname,"Lx");
- for (i = 0; i < 10; i++) {
- kname[1] = i + '0';
- K[10 + i] = tgetstr(kname, &p);
- lname[1] = i + '0';
- L[10 + i] = tgetstr(lname, &p);
- }
-
- /* Get the rest of the sequences */
- KS = tgetstr("ks", &p);
- KE = tgetstr("ke", &p);
- KH = tgetstr("kh", &p);
- KU = tgetstr("ku", &p);
- KD = tgetstr("kd", &p);
- KL = tgetstr("kl", &p);
- KR = tgetstr("kr", &p);
- #endif
-
- if(CM == NULL || UP == NULL)
- panic("This terminal is to stupid to run MicroGnuEmacs\n");
- ttresize(); /* set nrow & ncol */
-
- /* watch out for empty capabilities (sure to be wrong) */
- if (CE && !*CE) CE = NULL;
- if (CS && !*CS) CS = NULL;
- if (SR && !*SR) SR = NULL;
- if (AL && !*AL) AL = NULL;
- if (DL && !*DL) DL = NULL;
- if (pAL && !*pAL) pAL = NULL;
- if (pDL && !*pDL) pDL = NULL;
- if (CD && !*CD) CD = NULL;
-
- if(!CE) tceeol = ncol;
- else tceeol = charcost(CE);
-
- /* Estimate cost of inserting a line */
- if (CS && SR) tcinsl = charcost(CS)*2 + charcost(SR);
- else if (pAL) tcinsl = charcost(pAL);
- else if (AL) tcinsl = charcost(AL);
- else tcinsl = NROW * NCOL; /* make this cost high enough */
-
- /* Estimate cost of deleting a line */
- if (CS) tcdell = charcost(CS)*2 + 1;
- else if (pDL) tcdell = charcost(pDL);
- else if (DL) tcdell = charcost(DL);
- else tcdell = NROW * NCOL; /* make this cost high enough */
-
- /* Flag to indicate that we can both insert and delete lines */
- insdel = (AL || pAL) && (DL || pDL);
-
- if (p >= &tcapbuf[TCAPSLEN])
- panic("Terminal description too big!\n");
- if (TI && *TI) putpad (TI); /* init the term */
- }
-
- /*
- * Clean up the terminal, in anticipation of
- * a return to the command interpreter. This is a no-op
- * on the ANSI display. On the SCALD display, it sets the
- * window back to half screen scrolling. Perhaps it should
- * query the display for the increment, and put it
- * back to what it was.
- */
- tttidy() {
- if (TE && *TE) putpad (TE); /* set the term back to normal mode */
- #ifdef XKEYS
- ttykeymaptidy();
- #endif
- }
-
- /*
- * Move the cursor to the specified
- * origin 0 row and column position. Try to
- * optimize out extra moves; redisplay may
- * have left the cursor in the right
- * location last time!
- */
- ttmove(row, col) {
- char *tgoto();
-
- if (ttrow!=row || ttcol!=col) {
- putpad(tgoto(CM, col, row));
- ttrow = row;
- ttcol = col;
- }
- }
-
- /*
- * Erase to end of line.
- */
- tteeol() {
- if(CE) putpad(CE);
- else {
- register int i=ncol-ttcol;
- while(i--) ttputc(" ");
- ttrow = ttcol = HUGE;
- }
- }
-
- /*
- * Erase to end of page.
- */
- tteeop() {
- if(CD) putpad(CD);
- else {
- putpad(CE);
- if (insdel) ttdell(ttrow + 1, LI, LI - ttrow - 1);
- else { /* do it by hand */
- register int line;
- for (line = ttrow + 1; line <= LI; ++line) {
- ttmove(line, 0);
- tteeol();
- }
- }
- ttrow = ttcol = HUGE;
- }
- }
-
- /*
- * Make a noise.
- */
- ttbeep() {
- ttputc(BEL);
- ttflush();
- }
-
- /*
- * Insert nchunk blank line(s) onto the
- * screen, scrolling the last line on the
- * screen off the bottom. Use the scrolling
- * region if possible for a smoother display.
- * If no scrolling region, use a set
- * of insert and delete line sequences
- */
- ttinsl(row, bot, nchunk) {
- register int i;
-
- if (row == bot) { /* Case of one line insert is */
- ttmove(row, 0); /* special */
- tteeol();
- return;
- }
- if (CS && SR) { /* Use scroll region and back index */
- ttwindow(row,bot);
- ttmove(row, 0);
- while (nchunk--) putpad(SR);
- ttnowindow();
- return;
- } else if (insdel) {
- ttmove(1+bot-nchunk, 0);
- if (pDL) putpad (tgoto(pDL, 0, nchunk));
- else for (i=0; i<nchunk; i++) /* For all lines in the chunk */
- putpad(DL);
- ttmove(row, 0);
- if (pAL) putpad (tgoto(pAL, 0, nchunk));
- else for (i=0; i<nchunk; i++) /* For all lines in the chunk */
- putpad(AL);
- ttrow = HUGE;
- ttcol = HUGE;
- } else panic("ttinsl: Can't insert/delete line");
- }
-
- /*
- * Delete nchunk line(s) from "row", replacing the
- * bottom line on the screen with a blank line.
- * Unless we're using the scrolling region, this is
- * done with a crafty sequences of insert and delete
- * lines. The presence of the echo area makes a
- * boundry condition go away.
- */
- ttdell(row, bot, nchunk)
- {
- register int i;
-
- if (row == bot) { /* One line special case */
- ttmove(row, 0);
- tteeol();
- return;
- }
- if (CS) { /* scrolling region */
- ttwindow(row, bot);
- ttmove(bot, 0);
- while (nchunk--) ttputc(LF);
- ttnowindow();
- }
- else if(insdel) {
- ttmove(row, 0); /* Else use insert/delete line */
- if (pDL) putpad (tgoto(pDL, 0, nchunk));
- else for (i=0; i<nchunk; i++) /* For all lines in the chunk */
- putpad(DL);
- ttmove(1+bot-nchunk,0);
- if (pAL) putpad (tgoto(pAL, 0, nchunk));
- else for (i=0; i<nchunk; i++) /* For all lines in the chunk */
- putpad(AL);
- ttrow = HUGE;
- ttcol = HUGE;
- } else panic("ttdell: Can't insert/delete line");
- }
-
- /*
- * This routine sets the scrolling window
- * on the display to go from line "top" to line
- * "bot" (origin 0, inclusive). The caller checks
- * for the pathalogical 1 line scroll window that
- * doesn't work right, and avoids it. The "ttrow"
- * and "ttcol" variables are set to a crazy value
- * to ensure that the next call to "ttmove" does
- * not turn into a no-op (the window adjustment
- * moves the cursor).
- *
- */
- ttwindow(top, bot)
- {
- if (CS && (tttop!=top || ttbot!=bot)) {
- putpad(tgoto(CS, bot, top));
- ttrow = HUGE; /* Unknown. */
- ttcol = HUGE;
- tttop = top; /* Remember region. */
- ttbot = bot;
- }
- }
-
- /*
- * Switch to full screen scroll. This is
- * used by "spawn.c" just before is suspends the
- * editor, and by "display.c" when it is getting ready
- * to exit. This function gets to full screen scroll
- * by telling the terminal to set a scrolling regin
- * that is LI or nrow rows high, whichever is larger.
- * This behavior seems to work right on systems
- * where you can set your terminal size.
- */
- ttnowindow()
- {
- if (CS) {
- putpad(tgoto(CS, (nrow > LI ? nrow : LI) - 1, 0));
- ttrow = HUGE; /* Unknown. */
- ttcol = HUGE;
- tttop = HUGE; /* No scroll region. */
- ttbot = HUGE;
- }
- }
-
- /*
- * Set the current writing color to the
- * specified color. Watch for color changes that are
- * not going to do anything (the color is already right)
- * and don't send anything to the display.
- * The rainbow version does this in putline.s on a
- * line by line basis, so don't bother sending
- * out the color shift.
- */
- ttcolor(color) register int color; {
- if (color != tthue) {
- if (color == CTEXT) { /* Normal video. */
- putpad(SE);
- } else if (color == CMODE) { /* Reverse video. */
- putpad(SO);
- }
- tthue = color; /* Save the color. */
- }
- }
-
- /*
- * This routine is called by the
- * "refresh the screen" command to try and resize
- * the display. The new size, which must be deadstopped
- * to not exceed the NROW and NCOL limits, it stored
- * back into "nrow" and "ncol". Display can always deal
- * with a screen NROW by NCOL. Look in "window.c" to
- * see how the caller deals with a change.
- */
- ttresize() {
- setttysize(); /* found in "ttyio.c", */
- /* ask OS for tty size */
- if (nrow < 1) /* Check limits. */
- nrow = 1;
- else if (nrow > NROW)
- nrow = NROW;
- if (ncol < 1)
- ncol = 1;
- else if (ncol > NCOL)
- ncol = NCOL;
- }
-
- #ifdef NO_RESIZE
- static setttysize() {
- nrow = tgetnum("li");
- ncol = tgetnum("co");
- }
- #endif
-
- static int cci;
-
- static /* fake char output for charcost() */
- fakec(c) char c; {
- #ifdef lint
- c++;
- #endif
- cci++;
- }
-
- /* calculate the cost of doing string s */
- charcost (s) char *s; {
- cci = 0;
-
- tputs(s, nrow, fakec);
- return cci;
- }
-
- putpad(str) char *str; {
- tputs(str, 1, ttputc);
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'tty/termcap/readme'
- then
- echo shar: will not over-write existing file "'tty/termcap/readme'"
- else
- cat << \SHAR_EOF > 'tty/termcap/readme'
-
- MicroGnuEmacs Termcap Terminal Capabilities
-
- The termcap library needs to know where to get the terminal type and
- termcap capibilities file from. UNIX and Os9/68k users should "setenv
- TERM" to their terminal type, and "setenv TERMCAP" if they are using a
- non-standard termcap file. VMS users should see AAAREADME.1ST for
- information on how to define the logical names TERM and ETC to point
- to the termcap definition file. Users of other operating systems
- should do the aproprate thing. For an example of a termcap file, UNIX
- users may look in /etc/termcap, Os9/68k users may look at
- /dd/sys/termcap (if present), and VMS users should see the file
- [.SYS.VMS.TERMCAP]TERMCAP.
-
- MicroGnuEmacs requires that certain terminal capabilities exist in the
- specified termcap entry. The "cm" (cursor motion) capability *must*
- be available to use MicroGnuEmacs. (Yes, it is possible to fake cm
- with some other capibilities, but MicroGnuEmacs doesn't try.) If your
- terminal is one that uses control characters in the paramater portion
- of the "cm" string, the "up" and "bc" capabilites may also be needed.
- (See your termlib documentation for when this is so.)
-
- If the following capabilities are available, they are used. The AL
- and DL sequences are not totally standard, but having them improves
- the performance of the editor, since it doesn't have to redraw the
- screen to delete a line. They should not be used if they need control
- characters as paramaters.
-
- cd -- clear display
- ce -- clear to eol
-
- al -- insert 1 line
- dl -- delete 1 line
-
- AL -- parametrized insert line (note capitalization)
- DL -- parametrized delete line (note capitalization)
-
- ti -- cursor movement initialization string
- te -- cursor movement end string
-
- The cs capability is not as standard as some of the other
- capibilities, but is used by MicroGnuEmacs when available. It is used
- to define a "scrolling region", which defines a window within the
- screen where all the action takes place. A newline character at the
- bottom of this area scrolls the rest of the text in the area up one
- line, just like the normal screen; a reverse linefeed (sr) at the top
- of the window moves all the text in the area down a line.
- MicroGnuEmacs does not properly handle "cs" if your terminal needs
- control characters as paramaters, and in this case "cs" should not be
- defined.
-
- If the cs and sr capabilities are available, the termcap driver uses
- these to make the insert/delete line functions work more smoothly. If
- only the cs capability is present, it is still used for the delete
- line function, but not for inserting lines.
-
- The definition of the cs capability is: the first parameter in the
- sequence defines the first row (origin 0) that is in the scrolling
- region, and the second argument defines the last row to include in the
- scrolling region.
-
- cs -- set scrolling region (arg1 = top, arg2 = bottom)
- sr -- reverse index
-
- The following capabilities provide for an enhanced (reverse-video
- or otherwise rendered) mode line. The sg entry should not be present
- on terminals that do this to characters as they are placed on the
- screen. Terminals that put a region of the screen in the standout
- mode should have sg defined as numeric: :sg#0: for terminals that do
- this on regions but don't take any character positions to do this,
- (this may be a non-standard interprition of the meaning of sg) and the
- number of character positions taken by any other terminal.
-
- so -- enter standout mode
- se -- leave standout mode
- sg -- number of character positions used by standout
-
- Function Keys
-
- If MicroGnuEmacs is compiled with XKEYS defined, a new feature of the
- termcap driver is support for function keys, based on the termcap
- entry that defines the terminal. This may not be be deisriable in all
- cases, especially those in which the terminal in use does not use ESC
- as the first character of all arrow and function keys. If you do
- deside to use this feature, don't expect it to work with all terminal
- types. Those termial types it doesn't work with will have to use
- modified termcaps that do not include the termcap sequences described
- below to be useful with MicroGnuEmacs compiled with the XKEYS option.
- XKEYS also interferes with the proper operation of delayed prompts.
-
- The termcap "standard" provides for a number of sequences that define
- how to activate the function keys, what the function key sequences
- are, and the names of the function keys. The termcap driver uses the
- following capabilities to parse for function key sequences:
-
- ks -- start using function keys
- ke -- finish using the function keypad
- kh -- home key
- ku -- up arrow
- kd -- down arrow
- kl -- left arrow
- kr -- right arrow
- k0-k9 -- standard termcap function keys (1-10)
- l0-l9 -- labels for same
-
- The following key capabilities are not standard, but are used if
- they are in the termcap:
-
- K0-K9 -- function keys 10 through 19
- L0-L9 -- labels for same
-
- For example, the DEC LK201 (vt200-series, VAXstation) keyboard has an
- editing keypad. A VT200 termcap entry could include the following
- capabilities to go into application keypad mode, set up the arrow keys,
- and map the editing keypad to internal function key codes KF0-KF7:
-
- ...the beginning of the termcap entry....
- :ks=\E[?1h\E=:ke=\E[?1l\E>:\
- :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kh=\E[H:\
- :k0=\E[28~:l0=Help:\
- :k1=\E[29~:l1=Do:\
- :k2=\E[1~:l2=Find:\
- :k3=\E[2~:l3=Insert Here:\
- :k4=\E[3~:l4=Remove:\
- :k5=\E[4~:l5=Select:\
- :k6=\E[5~:l6=Prev Screen:\
- :k7=\E[6~:l7=Next Screen:\
-
- There is one problem with supporting function keys: If the META
- introducer key (usually ESC) is used as the initial character of a
- function key sequence, how is the parser to know when the user intends
- the introducer to be taken at face value? The parser doesn't have
- enough information.
-
- The approach the current code takes is that if the META introducer is
- the first character in a function sequence, and the second character c
- isn't part of a function key sequence, the parser returns (KMETA | c).
- If it sees *two* META introducers in a row, it returns one instance of
- METACH. This approach is subject to discussion and debate, but it
- works right most of the time.
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'tty/termcap/ttydef.h'
- then
- echo shar: will not over-write existing file "'tty/termcap/ttydef.h'"
- else
- cat << \SHAR_EOF > 'tty/termcap/ttydef.h'
- /*
- * Termcap terminal file, nothing special, just make it big
- * enough for windowing systems.
- */
-
- #define GOSLING /* Compile in fancy display. */
- /* #define MEMMAP */ /* Not memory mapped video. */
-
- #define NROW 66 /* Rows. */
- #define NCOL 132 /* Columns. */
- /* #define MOVE_STANDOUT /* don't move in standout mode */
- #define STANDOUT_GLITCH /* possible standout glitch */
- #define TERMCAP /* for possible use in ttyio.c */
-
- /*
- * Termcap function keys. The last 10 keys correspond to the
- * non-standard termcap entries K0-K9 (instead of k0-k9).
- */
- #ifdef XKEYS
- #define KFIRST K01
- #define KLAST K1A
-
- #define KHOME K01
- #define KDOWN K02
- #define KUP K03
- #define KLEFT K04
- #define KRIGHT K05
- #define KF0 K06
- #define KF1 K07
- #define KF2 K08
- #define KF3 K09
- #define KF4 K0A
- #define KF5 K0B
- #define KF6 K0C
- #define KF7 K0D
- #define KF8 K0E
- #define KF9 K0F
- #define KF10 K10
- #define KF11 K11
- #define KF12 K12
- #define KF13 K13
- #define KF14 K14
- #define KF15 K15
- #define KF16 K16
- #define KF17 K17
- #define KF18 K18
- #define KF19 K19
- #define KF20 K1A
-
- #define NFKEYS 20 /* # of function keys (k0-k9, K0-K9) */
- #endif
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
-
-